﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MainWindow.cs" company="YellowFish">
//   Copyright © YellowFish 2009
// </copyright>
// <summary>
//   Describes and manipulates the main application window.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using Diagnostics.Annotations;

namespace MobilePal
{
  #region Imported Namespaces


  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Windows.Forms;

  using Collections;

  using Dialogs;

  using Log;

  using State;

  using Views;


  #endregion


  /// <summary>
  /// Describes and manipulates the main application window.
  /// </summary>
  public partial class MainWindow: Form
  {
    #region Constants and Fields


    private readonly Presenter _presenter;


    #endregion


    #region Constructors and Destructors


    /// <summary>
    /// Initializes a new instance of the <see cref="MainWindow"/> class.
    /// </summary>
    /// <param name="loggers">
    /// The loggers.
    /// </param>
    /// <param name="state">
    /// The state.
    /// </param>
    public MainWindow([NotNull] IEnumerable<ILogger> loggers, [NotNull] ApplicationState state)
    {
      State = state;
      Assert.ArgumentNotNull(loggers, "loggers");
      Assert.ArgumentNotNull(state, "state");

      InitializeComponent();

      _presenter = new Presenter(this, state);

      state.Settings.Views.CollectionChanged += ViewsCollectionChanged;

      BuildViewsMenu();
      BuildCurrentViewMenu();

      foreach (ILogger logger in loggers)
      {
        _presenter.Loggers.Add(logger);
      }

      _presenter.ActivityToggled += PresenterActivityToggled;
      _presenter.ActivitySelected += PresenterActivityToggled;
      _presenter.CurrentViewChanged += PresenterCurrentViewChanged;

      Activity selectedActivity = null;

      if (_presenter.CurrentView != null)
      {
        selectedActivity = _presenter.CurrentView.SelectedActivity;
      }

      UpdateToggleActivityMenuItems(selectedActivity);
    }


    #endregion


    #region Properties


    public ApplicationState State
    {
      get;
      private set;
    }


    #endregion


    #region Methods


    private void BuildCurrentViewMenu()
    {
      IView currentView = _presenter.CurrentView;
      currentViewMenuItem.MenuItems.Clear();

      if (currentView == null)
      {
        currentViewMenuItem.Enabled = false;
        return;
      }

      List<MenuItem> viewMenu = currentView.MenuItems;

      if (viewMenu == null || viewMenu.Count == 0)
      {
        currentViewMenuItem.Enabled = false;
        return;
      }

      currentViewMenuItem.Enabled = true;

      foreach (MenuItem item in viewMenu)
      {
        currentViewMenuItem.MenuItems.Add(item);
      }
    }


    private void BuildViewsMenu()
    {
      viewMenuItem.MenuItems.Clear();

      foreach (string label in _presenter.ViewsNames)
      {
        var item = new MenuItem();
        item.Text = label;
        item.Click += ViewMenuItemClick;

        viewMenuItem.MenuItems.Add(item);
      }
    }


    /// <summary>
    /// Closes the menu item click.
    /// </summary>
    /// <param name="sender">
    /// The sender.
    /// </param>
    /// <param name="e">
    /// The <see cref="System.EventArgs"/> instance containing the event data.
    /// </param>
    private void CloseMenuItemClick([NotNull] object sender, [NotNull] EventArgs e)
    {
      Assert.ArgumentNotNull(sender, "sender");
      Assert.ArgumentNotNull(e, "e");

      Close();
    }


    /// <summary>
    /// Customs the toggle time menu item click.
    /// </summary>
    /// <param name="sender">
    /// The sender.
    /// </param>
    /// <param name="e">
    /// The <see cref="System.EventArgs"/> instance containing the event data.
    /// </param>
    private void CustomToggleTimeMenuItemClick([NotNull] object sender, [NotNull] EventArgs e)
    {
      Assert.ArgumentNotNull(sender, "sender");
      Assert.ArgumentNotNull(e, "e");

      if (_presenter.CurrentView == null || _presenter.CurrentView.SelectedActivity == null)
      {
        return;
      }

      Activity selectedActivity = _presenter.CurrentView.SelectedActivity;

      SetTimeDialog dialog = Program.CreateSetTimeDialog(selectedActivity.LastToggleTime, DateTime.Now);
      dialog.MaxValueIsNow = true;

      DialogResult result = dialog.ShowDialog();

      if (result == DialogResult.OK)
      {
        selectedActivity.ToggleIsInProgress(dialog.Value);
      }
    }


    private void ManageActivitiesMenuItemClick(object sender, EventArgs e)
    {
      var dialog = new ActivitiesListDialog(State.Activities, State.Categories);
      dialog.ShowDialog();
    }


    private void ManageCategoriesMenuItemClick(object sender, EventArgs e)
    {
      var dialog = new CategoriesListDialog(State.Categories);
      dialog.ShowDialog();
    }


    private void ManageRulesMenuItemClick(object sender, EventArgs e)
    {
      var dialog = new RulesListDialog(State.Rules, State.Activities, State.Categories);
      dialog.ShowDialog();
    }


    private void ManageViewsMenuItemClick(object sender, EventArgs e)
    {
      var dialog = new ViewsListDialog(State.Settings.Views);
      dialog.ShowDialog();
    }


    /// <summary>
    /// Presenters the activity toggled.
    /// </summary>
    /// <param name="sender">
    /// The sender.
    /// </param>
    /// <param name="activityArgs">
    /// The activity event arguments.
    /// </param>
    private void PresenterActivityToggled([NotNull] object sender, [NotNull] ActivityEventArgs activityArgs)
    {
      Assert.ArgumentNotNull(sender, "sender");
      Assert.ArgumentNotNull(activityArgs, "activityArgs");

      Activity activity = activityArgs.Activity;

      UpdateToggleActivityMenuItems(activity);
    }


    private void PresenterCurrentViewChanged(object sender, EventArgs e)
    {
      BuildCurrentViewMenu();
    }


    /// <summary>
    /// Toggles the activity menu item click.
    /// </summary>
    /// <param name="sender">
    /// The sender.
    /// </param>
    /// <param name="e">
    /// The <see cref="System.EventArgs"/> instance containing the event data.
    /// </param>
    private void ToggleActivityMenuItemClick([NotNull] object sender, [NotNull] EventArgs e)
    {
      Assert.ArgumentNotNull(sender, "sender");
      Assert.ArgumentNotNull(e, "e");

      _presenter.CurrentView.ToggleSelectedActivity();
    }


    private void UpdateToggleActivityMenuItems([CanBeNull] Activity activity)
    {
      if (activity != null)
      {
        toggleActivityMenuItem.Enabled = true;
        toggleActivityMenuItem.Text = activity.IsInProgress ? "Stop" : "Start";

        customToggleTimeMenuItem.Enabled = true;
        customToggleTimeMenuItem.Text = activity.IsInProgress ? "Stop Activity..." : "Start Activity...";
      }
      else
      {
        toggleActivityMenuItem.Enabled = false;
        customToggleTimeMenuItem.Enabled = false;
      }
    }


    /// <summary>
    /// Views the menu item click.
    /// </summary>
    /// <param name="sender">
    /// The sender.
    /// </param>
    /// <param name="e">
    /// The <see cref="System.EventArgs"/> instance containing the event data.
    /// </param>
    private void ViewMenuItemClick([NotNull] object sender, [NotNull] EventArgs e)
    {
      Assert.ArgumentNotNull(sender, "sender");
      Assert.ArgumentNotNull(e, "e");

      var menuItem = (MenuItem)sender;

      if (_presenter.CurrentView.Name == menuItem.Text)
      {
        return;
      }

      IView view = _presenter.GetViewLabel(menuItem.Text);

      if (view != null)
      {
        _presenter.CurrentView = view;
        UpdateToggleActivityMenuItems(view.SelectedActivity);
      }
    }


    private void ViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs<ApplicationView> e)
    {
      BuildViewsMenu();
    }


    #endregion
  }
}